import java.io.*;
import java.util.ArrayList;
import java.util.List;

import org.lwjgl.opengl.GL11;
import javax.vecmath.Vector3f;

import texture.*;

import texture.*;
import org.lwjgl.opengl.ARBFragmentProgram;
import org.lwjgl.opengl.ARBTextureCubeMap;
import org.lwjgl.opengl.ARBVertexProgram;
import org.lwjgl.opengl.ARBMultitexture;
import org.lwjgl.opengl.GL13;

public class BSP {

	protected final static int SIZE_OF_VERTEX_LUMP=44;			//helps us calculate number of vertexes 10*float(4)+4*byte
	protected final static int SIZE_OF_INDEX_LUMP=4;
	protected final static int SIZE_OF_FACE_LUMP=104;
	protected final static int SIZE_OF_TEXTURE_LUMP=72;
	protected final static int SIZE_OF_PLANE_LUMP=16;
	protected final static int SIZE_OF_NODE_LUMP=36;
	protected final static int SIZE_OF_LEAF_LUMP=48;
	protected final static int SIZE_OF_LEAF_FACE_LUMP=4;
	protected final static int SIZE_OF_LIGHTMAP_LUMP=49152;
	
	protected static RandomAccessFile in;
	protected static byte b[] = new byte[4];
	protected static int numOfVertices;
	protected static int numOfIndices;
	protected static int numOfFaces;
	protected static int numOfTextures;
	protected static int numOfNodes;
	protected static int numOfPlanes;
	protected static int numOfLeafs;
	protected static int numOfLightMaps;
	protected static int numOfLeafFaces;
	protected static int index[];
	protected static Face f[];
	protected static BSPHeader header;
	protected static BSPLump lumps[];
	protected static BSPVertex vertex[];
	protected static BSPNode node[];
	protected static BSPPlane plane[];
	protected static BSPLeaf leaf[];
	protected static BSPLeafFace leafface[];
	protected static BSPTexture t[];
	protected static BSPLightMap lm[];
	protected static BSPVisData visdata;
	protected static Physics physics_model;
	protected static boolean lightMappingEnabled; 
	  
	 // This function creates a display list (for later rendering) for all the triangles of all faces
	 // Loop through all faces => then Loop through all indices of a face
	 // Every three indices make a triangle
	 // here we also add all faces to physics engine
	  
	  protected static void CreateDisplayListFromBSP() {
		  
		  int index = GL11.glGenLists(BSP.numOfFaces); //create pointer to first display list
		  TextureLoader loader = new TextureLoader();
		  
		  physics_model = new Physics();	//create new physics model
		  
		   for(int i = 0; i < BSP.numOfFaces; i++) {	//we go through all faces
		    	
			   // We only need faces of type 1
		    	if(BSP.f[i].type != 1) continue;
		    	
		    	int numFirstIndex = BSP.f[i].startIndex;
		    	int numIndices = BSP.f[i].numOfIndices;
		    	int startVertexIndex = BSP.f[i].startVertIndex;
		    	int numVertices = BSP.f[i].numOfVerts;
		    	GL11.glNewList(index+i, GL11.GL_COMPILE);	//create a new display list for one face
		    
		    	GL13.glActiveTexture(GL13.GL_TEXTURE0);
		    	GL11.glEnable(GL11.GL_TEXTURE_2D);
		    	// Loads the texture of this face and binds the GL context
		    	if(BSP.t[BSP.f[i].textureID].exists == true) {
		    		try {                     
		    			Texture texture = loader.getTexture(BSP.t[BSP.f[i].textureID].textureName);
		    			texture.bind();
		    		}	
		    		catch (IOException e) {
						//e.printStackTrace();
					}
		    	}
		    	
		    	// IF lightmapping is enabled we load the lightmapping textures and bind them to OpenGL context
		    	// We are using multitexturing to bind the second texture (GL_TEXTURE1) over the first one (GL_TEXTURE0)
		    	if(lightMappingEnabled == true) {
			    	GL13.glActiveTexture(GL13.GL_TEXTURE1);
			    	GL11.glEnable(GL11.GL_TEXTURE_2D);
			    	int lightMapID = BSP.f[i].lightmapID;
					if(lightMapID >= 0 && BSP.lm[lightMapID].data.length != 0) {
						//System.out.println(BSP.lm[lightMapID].data.length);
						Texture lightmap = loader.getLightMap(lightMapID, BSP.lm[lightMapID].data);
					    lightmap.bind();
					}
					GL13.glActiveTexture(GL13.GL_TEXTURE0);	//now we switch texture slot to 0, for further texturing (that texturing works for model)
		   		}
				
		    	for(int j = 0; j < numIndices; j+= 3) {
		    		int i0 = BSP.index[numFirstIndex + 2];
		    		int i1 = BSP.index[numFirstIndex + 1];
		    		int i2 = BSP.index[numFirstIndex + 0];
		    		
		    		GL11.glBegin(GL11.GL_POLYGON); 	 	   
		    		GL13.glMultiTexCoord2f(GL13.GL_TEXTURE0, BSP.getVertex(startVertexIndex + i0).colorMap_X, BSP.getVertex(startVertexIndex + i0).colorMap_Z);
		    		if(lightMappingEnabled == true) GL13.glMultiTexCoord2f(GL13.GL_TEXTURE1,BSP.getVertex(startVertexIndex + i0).lightMap_X, BSP.getVertex(startVertexIndex + i0).lightMap_Z);
		    		GL11.glVertex3f(BSP.getVertex(startVertexIndex + i0).position_X, BSP.getVertex(startVertexIndex + i0).position_Y, BSP.getVertex(startVertexIndex + i0).position_Z);
                    
		    		GL13.glMultiTexCoord2f(GL13.GL_TEXTURE0, BSP.getVertex(startVertexIndex + i1).colorMap_X, BSP.getVertex(startVertexIndex + i1).colorMap_Z);
		    		if(lightMappingEnabled == true) GL13.glMultiTexCoord2f(GL13.GL_TEXTURE1,BSP.getVertex(startVertexIndex + i1).lightMap_X, BSP.getVertex(startVertexIndex + i1).lightMap_Z);
		    		GL11.glVertex3f(BSP.getVertex(startVertexIndex + i1).position_X, BSP.getVertex(startVertexIndex + i1).position_Y, BSP.getVertex(startVertexIndex + i1).position_Z);
                    
                    GL13.glMultiTexCoord2f(GL13.GL_TEXTURE0, BSP.getVertex(startVertexIndex + i2).colorMap_X, BSP.getVertex(startVertexIndex + i2).colorMap_Z);       
                    if(lightMappingEnabled == true) GL13.glMultiTexCoord2f(GL13.GL_TEXTURE1, BSP.getVertex(startVertexIndex + i2).lightMap_X, BSP.getVertex(startVertexIndex + i2).lightMap_Z);
                    GL11.glVertex3f(BSP.getVertex(startVertexIndex + i2).position_X, BSP.getVertex(startVertexIndex + i2).position_Y, BSP.getVertex(startVertexIndex + i2).position_Z);
                    GL11.glEnd();
		    		
			 	    numFirstIndex += 3;
		    	}
		    	
		    	GL11.glEndList();
		    	
		    	//add a face to physics model, current face is from numVertices vertices and start at vertex no. startVertexIndex
		    	Vector3f currentVertex;
		    	List <Vector3f> faceVertices = new ArrayList <Vector3f>();
		    	for(int k=0;k<numVertices;k++){
		    		currentVertex = new Vector3f(vertex[startVertexIndex+k].position_X,vertex[startVertexIndex+k].position_Y,vertex[startVertexIndex+k].position_Z);
		    		faceVertices.add(currentVertex);
		    	}
		    	physics_model.addStaticObject(faceVertices);
		   }
	  }
	  
	public static void LoadBSPHeader() {
		try {
			//init the header and lump struct.
			header = new BSPHeader();
			lumps = new BSPLump[17]; //there are 17 different lupms			
			//read header and lump data
			for(int i=0;i<4;i++) //stringID is 4 char long
				header.strID+=(char)in.read();
			
			for(int i=0;i<4;i++)					//assembling bytes for endian switch
				b[i]=(byte)in.readUnsignedByte();
			
			header.version = endianSwitchInt(b);	
		
			for(int i=0;i<17*8;i++){				
											
				b[i%4]=(byte)in.readUnsignedByte();			
					
				// First 4 bytes are the offset
				// Create a new lump and set the offset to the already read 4 bytes
				if(i!=0&&i%8==3){
					lumps[i/8] = new BSPLump();
					lumps[i/8].offset = endianSwitchInt(b);
				}
				
				// After the 4 bytes of offset there are 4 bytes describing the size(length)
				// Set lump length
				if(i!=0&&i%8==7){
					lumps[i/8].length = endianSwitchInt(b);
				}	
			}
		}
			catch (IOException e) {
				System.out.println("Error reading file");
			}
	}
	 
	public static void LoadBSPVertices() {
		numOfVertices = lumps[10].length/SIZE_OF_VERTEX_LUMP;				
		vertex = new BSPVertex[numOfVertices];
		
		try {
		in.seek(lumps[10].offset);				//moving pointer to vertex lump
		
		for(int j=0;j<numOfVertices;j++){
			vertex[j] = new BSPVertex();
			vertex[j].position_X=readFloat();	//position x
			vertex[j].position_Y=readFloat();	//position y
			vertex[j].position_Z=readFloat();	//position z
			vertex[j].colorMap_X=readFloat();	//color map x
			vertex[j].colorMap_Z=readFloat();	//color map z
			vertex[j].lightMap_X=readFloat();	//light map x
			vertex[j].lightMap_Z=readFloat();	//light map z
			vertex[j].normal_X=readFloat();		//normal x
			vertex[j].normal_Y=readFloat();		//normal y		
			vertex[j].normal_Z=readFloat();		//normal z
			
			for(int i=0;i<4;i++)			//vertex color
				b[i]=(byte)in.readUnsignedByte();
			
			vertex[j].red=b[0];
			vertex[j].green=b[1];
			vertex[j].blue=b[2];
			vertex[j].alpha=b[3];
			
			// Switch Y and Z position and negate Z
			// We need to do the switch because Quake uses a different coordinate system
			float temp = vertex[j].position_Y;
			vertex[j].position_Y = vertex[j].position_Z;
			vertex[j].position_Z = -temp;
			}
		
	} catch (IOException e) {
		System.out.println("Error reading file");
		}
	}
	
	public static void LoadBSPFaces() {
		try {
			//init FACES and read them
			numOfFaces = lumps[13].length/SIZE_OF_FACE_LUMP;
			f = new Face[numOfFaces];
			in.seek(lumps[13].offset);
			
			for(int i=0;i<numOfFaces;i++){
				f[i] = new Face();
				f[i].textureID = readInt();
				f[i].effect = readInt();
				f[i].type = readInt();
				f[i].startVertIndex = readInt();
				f[i].numOfVerts = readInt();
				f[i].startIndex = readInt();
				f[i].numOfIndices = readInt();
				f[i].lightmapID = readInt();
				f[i].MapCorner1 = readInt();
				f[i].MapCorner2 = readInt();
				f[i].MapSize1 = readInt();
				f[i].MapSize2 = readInt();
				f[i].MapPos_X = readFloat();
				f[i].MapPos_Y = readFloat();
				f[i].MapPos_Z = readFloat();
				f[i].MapVecs_XS = readFloat();
				f[i].MapVecs_YS = readFloat();
				f[i].MapVecs_ZS = readFloat();
				f[i].MapVecs_XT = readFloat();
				f[i].MapVecs_YT = readFloat();
				f[i].MapVecs_ZT = readFloat();
				f[i].vNormal_X = readFloat();
				f[i].vNormal_Y = readFloat();
				f[i].vNormal_Z = readFloat();
				f[i].size1 = readInt();
				f[i].size2 = readInt();
			}
			
		}
		catch (IOException e) {
			System.out.println("Error reading file");
			}
		
	}
	
	public static void LoadBSPNodes() {
		try {

			// Read nodes lump
			numOfNodes = lumps[3].length / SIZE_OF_NODE_LUMP;
			in.seek(lumps[3].offset);
			node = new BSPNode[numOfNodes];
			
			for(int i = 0; i < numOfNodes; i++) {
				node[i] = new BSPNode();
				node[i].plane = readInt();
				node[i].front = readInt();
				node[i].back = readInt();
				for(int j = 0; j < 3; j++) {
					node[i].mins[j] = readInt();
					node[i].maxs[j] = readInt();
				}
			}
		}
		catch (IOException e) {
			System.out.println("Error reading file");
			}
	}
	
	public static void LoadBSPIndices() {
		try {
			//init INDICES and read them
			numOfIndices = lumps[11].length/SIZE_OF_INDEX_LUMP;
			index = new int[numOfIndices];
			in.seek(lumps[11].offset);	//start reading at the index lump
			
			for(int i=0;i<numOfIndices;i++){
				index[i]=readInt();
			}
		}
		catch (IOException e) {
			System.out.println("Error reading file");
			}
	}
	
	public static void LoadBSPLightMaps() {
		try {
			// read lightmap data (lightmap textures are included in the BSP file as 128x128 images
		    //and then create textures with this data
			numOfLightMaps = lumps[14].length / SIZE_OF_LIGHTMAP_LUMP;
			System.out.println("Num of lightmaps: " + numOfLightMaps);
			in.seek(lumps[14].offset);
			lm = new BSPLightMap[numOfLightMaps];
	
			for(int l = 0; l < numOfLightMaps; l++)  {
				lm[l] = new BSPLightMap();
				for(int i = 0; i < 128*128*3; i++) {
					
							lm[l].data[i] = (byte)in.readUnsignedByte();
					
				}
				
				//loader.getLightMap("lightmap" + Integer.toString(l), lm.data);
			}
		}
		
		catch (IOException e) {
			System.out.println("Error reading file");
			}
		
		
		
	}
	public static void LoadBSPLeafs() {
		try {
			// Read leaf lump
			numOfLeafs = lumps[4].length / SIZE_OF_LEAF_LUMP;
			in.seek(lumps[4].offset);
			leaf = new BSPLeaf[numOfLeafs];
			for(int i = 0; i < numOfLeafs; i++) {
				leaf[i] = new BSPLeaf();
				leaf[i].cluster = readInt();
				leaf[i].area = readInt();
				
				for(int j = 0; j < 3; j++) {
					leaf[i].mins[j] = readInt();
					leaf[i].maxs[j] = readInt();
				}
				
				leaf[i].leafface = readInt();
				leaf[i].n_leaffaces = readInt();
				leaf[i].leafbrush = readInt();
				leaf[i].n_leafbrushes = readInt();
				
			}
		}
		catch (IOException e) {
			System.out.println("Error reading file");
			}
	}
	
	public static void LoadBSPLeafFaces() {
		try {
			// Read leaf faces lump
			numOfLeafFaces = lumps[5].length / SIZE_OF_LEAF_FACE_LUMP;
			in.seek(lumps[5].offset);
			leafface = new BSPLeafFace[numOfLeafFaces];
			for(int i = 0; i < numOfLeafFaces; i++) {
				leafface[i] = new BSPLeafFace();
				leafface[i].cluster = readInt();
			}
		}
		catch (IOException e) {
			System.out.println("Error reading file");
			}
	}
	
	public static void LoadBSPPlanes() {
		try {
			// Read planes lump
			numOfPlanes = lumps[2].length / SIZE_OF_PLANE_LUMP;
			in.seek(lumps[2].offset);
			plane = new BSPPlane[numOfPlanes];
			for(int i = 0; i < numOfPlanes; i++) {
				plane[i] = new BSPPlane();
				for(int j = 0; j < 3; j++) {
					plane[i].normal[j] = readFloat();
				}
				plane[i].dist = readFloat();
			}
		}
		
		catch (IOException e) {
			System.out.println("Error reading file");
			}
		
	}
	
	public static void LoadBSPVisibilityData() {
		try {
			// Read visibility lump
			in.seek(lumps[16].offset);
			visdata = new BSPVisData();
			visdata.n_vecs = readInt();
			visdata.sz_vecs = readInt();
			visdata.vecs = new int[visdata.n_vecs * visdata.sz_vecs];
			
			for(int j = 0; j < visdata.n_vecs * visdata.sz_vecs; j++) {
				visdata.vecs[j] = in.readUnsignedByte();
				//System.out.println("byte is " + visdata.vecs[j]);
			}
		}
		catch (IOException e) {
			System.out.println("Error reading file");
			}
	}
	
	public static void LoadBSPTextures() {
		try {
			//init TEXTURES and read them
			numOfTextures = lumps[1].length/SIZE_OF_TEXTURE_LUMP;
			t = new BSPTexture[numOfTextures];
			
			in.seek(lumps[1].offset);
			
			
			for(int i=0;i<numOfTextures;i++){
				t[i] = new BSPTexture();
				t[i].exists = false;
				String temp="";
				for(int j=0;j<64;j++){	//reading 64 bytes (each byte is char)
					b[0]=(byte)in.readUnsignedByte();
					if(b[0] != 0) {
					temp+=(char)b[0];
					}
					
				}
				
				// This creates the full filename and path for the image of the texture and puts it into
				// string t[i].textureName
				
				if(temp.lastIndexOf('/') >= 0) {
				
				String dirName = temp.substring(0, temp.lastIndexOf('/'));
				String fileName = temp.substring(temp.lastIndexOf('/') + 1);
				File dir = new File(dirName);
				String[] children = dir.list(); //java's ls
				if (children == null) { 
				System.out.println("Dir doesnt exist or no files");
				} else { 
				for (int j=0; j<children.length; j++) { 
					if(children[j].startsWith(fileName + ".") == true) {
						System.out.println(children[j]);
						fileName = children[j];	//here we add extension to file (eg. neki -> neki.jpg)
						t[i].exists = true;
					}
				} 
				}
				
				
				t[i].textureName = System.getProperty("user.dir") + "/" + dirName + "/" + fileName;
				
				}
			    
				t[i].flags = readInt();
				t[i].contents = readInt();
				
				
			}
		}
		catch (IOException e) {
			System.out.println("Error reading file");
		}
	}
	
	public static boolean LoadBSP(String filename){
		
		try {
			//opening the .bsp file for binary reading
			in = new RandomAccessFile(filename,"rw");
				
			// read header
			LoadBSPHeader();
			LoadBSPVertices();
			LoadBSPFaces();
			LoadBSPIndices();
			LoadBSPLeafs();
			LoadBSPLeafFaces();
			LoadBSPNodes();
			LoadBSPPlanes();
			LoadBSPVisibilityData();
			LoadBSPTextures();
			LoadBSPLightMaps();
			in.close();
			
		
		} catch (FileNotFoundException e) {
			System.out.println("File not found!");
			return false;
		} catch (IOException e) {
			System.out.println("Error in file!");
		} 
		return true;
	}

	//other functions
	
    public static int endianSwitchInt(byte[] b){
        long l=(long)b[0] & 0xFF;
        l+=((long)b[1] & 0xFF) << 8;
        l+=((long)b[2] & 0xFF) << 16;
        l+=((long)b[3] & 0xFF) << 24;
        
        return (int)l;
    }
	
	public static int readInt() throws IOException{
		for(int i=0;i<4;i++)				
			b[i]=(byte)in.readUnsignedByte();
													//java uses big endian, but in .bsp files
		long l=(long)b[0] & 0xFF;					//the little endian is used
		l+=((long)b[1] & 0xFF) << 8;				//therefore the switch of an endian
		l+=((long)b[2] & 0xFF) << 16;				//must be performed
		l+=((long)b[3] & 0xFF) << 24;
		
		return (int)l;
	}

	public static float readFloat() throws IOException{
		for(int i=0;i<4;i++)				
			b[i]=(byte)in.readUnsignedByte();
		
		int i=(int)b[0] & 0xFF;
		i|=((int)b[1] & 0xFF) << 8;
		i|=((int)b[2] & 0xFF) << 16;
		i|=((int)b[3] & 0xFF) << 24;

		return Float.intBitsToFloat(i);
	}
	
	// Returns number of vertices in the BSP map structure
	public static int getNumOfVertices() {
		return numOfVertices;
	}
	
	public static Physics get_physicModel(){
		return physics_model;
	}
	
	// This function takes our camera position (x, y, z parameters) and goes
	// through the BSP nodes, starting at the root node and finally finding the
	// leaf node that our camera is currently in. 
	public static int FindLeaf(float x, float y, float z) {
		int i = 0;
		float distance = 0.0f;
		
		while(i >= 0) {
			BSPNode n = node[i];
			BSPPlane p = plane[n.plane];
			
			// Calculate the distance using the plane equation Ax + by + Cz + D = 0
			distance = (p.normal[0] + x) + (p.normal[1] + y) + (p.normal[2] + z) - p.dist;
			
			if(distance >= 0) {
				i = n.front;
			}
			else {
				i = n.back;
			}
		}
		
		// Return the leaf index
		return -(i+1);
	}
	
	
	// Returns if the current cluster can see the test cluster
	public static boolean IsClusterVisible(int current, int test) {
		if(visdata.n_vecs <= 0 || visdata.sz_vecs <= 0 || current < 0) return true;
		int visSet = visdata.vecs[ (current * visdata.sz_vecs) + (test/8)];
		
		int result = visSet & (1 << (test & 7));
		if(result > 0) return true;
		return false;
		
		
	}
	
	// Returns vertex at index at position i
	// If invalid position is given an empty vertex is returned
	public static BSPVertex getVertex(int i) {
		if(i < 0 || i >= numOfVertices) {
			return new BSPVertex();
		}
		return vertex[i];
	}
	
	
	//structures used for reading
	
	protected static class BSPHeader{
		protected String strID=""; // This should be always be 'IBSP'
		protected int version;	//0x2e for Quake3 files
	}
	protected static class BSPLump{
		protected int offset;	//The offset into the file for the start of this lump
		protected int length;	//The length in bytes for this lump
	}
	protected static class BSPVertex{
		protected float position_X, position_Y, position_Z; //Every vertex consists of: position
		protected float colorMap_X, colorMap_Z; 			//texture coordinates for color map 2 coordinates
		protected float lightMap_X, lightMap_Z; 			//texture coordinates for light map 2 coordinates
		protected float normal_X, normal_Y, normal_Z;		//vertex normal
		protected byte  red, green, blue, alpha; 			//vertex color ...not sure about alpha(alpha=transparency)...
												 			//byte must be unsigned, not sure how to declare that in java
												 			//it will have to do for now
		public void print(){
			System.out.println("x:"+position_X+"  y:"+position_Y+"  z:"+position_Z);
			System.out.println("color x:"+colorMap_X+"  color z:"+colorMap_Z);
			System.out.println("light x:"+lightMap_X+"  light z:"+lightMap_Z);
			System.out.println("norm x:"+normal_X+"  norm y:"+normal_Y+"  norm z:"+normal_Z);
			System.out.println("red:"+red+"  green:"+green+"  blue:"+blue+"  alpha:"+alpha);
		}
	}
	protected static class Face{
	    protected int textureID;							// The index into the texture array 
	    protected int effect;								// The index for the effects (or -1 = n/a) 
	    protected int type;									// 1=polygon, 2=patch, 3=mesh, 4=billboard 
	    protected int startVertIndex;						// The starting index into this face's first vertex 
	    protected int numOfVerts;							// The number of vertices for this face 
	    protected int startIndex;							// The starting index into the indices array for this face
	    protected int numOfIndices;							// The number of indices for this face
	    protected int lightmapID;							// The texture index for the lightmap 
	    protected int MapCorner1, MapCorner2;				// The face's lightmap corner in the image 
	    protected int MapSize1, MapSize2;					// The size of the lightmap section 
	    protected float MapPos_X, MapPos_Y, MapPos_Z;		// The 3D origin of lightmap. 
	    protected float MapVecs_XS, MapVecs_XT, MapVecs_YS, MapVecs_YT, MapVecs_ZS, MapVecs_ZT;	// The 3D space for s and t unit vectors. 
	    protected float vNormal_X, vNormal_Y, vNormal_Z;	// The face normal. 
	    protected int size1, size2;							// The bezier patch dimensions. 
	}
	
	protected static class BSPNode {
		int plane;
		int front;
		int back;
		int mins[] = new int[3];
		int maxs[] = new int[3];
		
	}
	
	protected static class BSPLeaf {
		int cluster;
		int area;
		int mins[] = new int[3];
		int maxs[] = new int[3];
		int leafface;
		int n_leaffaces;
		int leafbrush;
		int n_leafbrushes;
	}
	
	protected static class BSPLeafFace {
		int cluster;
	}
	
	protected static class BSPPlane {
		float normal[] = new float[3];
		float dist;
	}
	
	protected static class BSPVisData {
		int n_vecs;
		int sz_vecs;
		int vecs[];
	}
	
	protected static class BSPLightMap {
		protected byte data[] = new byte[128 * 128 * 3];
	}
	
	protected static class BSPTexture{
		protected String textureName;	//The name of the texture
		protected int flags, contents;	//Surface and content flags
		protected boolean exists;
		public void print(){
			System.out.println("name: "+ textureName);
			System.out.println("flags: "+flags);
			System.out.println("contents "+contents);
			
		}
	}

}
